<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <canvas id="c" width="500" height="400"></canvas>
    <script type="notjs" id="vertex">
        // 一个属性值，将会从缓冲中获取数据
        attribute vec4 a_position;
        uniform vec2 u_resolution;
        // 所有着色器都有一个main方法
        void main() {
            vec2 clipSpace = a_position.xy / u_resolution * 2.0;
            // gl_Position 是一个顶点着色器主要设置的变量
            gl_Position = vec4(clipSpace, 0, 1.0);
        }
    </script>
    <script type="notjs" id="fragment">
        // 片断着色器没有默认精度，所以我们需要设置一个精度
        // mediump是一个不错的默认值，代表“medium precision”（中等精度）
        precision mediump float;
        uniform vec4 f_color;
        void main() {
        // gl_FragColor是一个片断着色器主要设置的变量
        // gl_FragColor = vec4(1, 0, 0.5, 1); // 返回“瑞迪施紫色”
            gl_FragColor = f_color;
        }
    </script>
    <script>
        var oCanvas = document.getElementById('c');
        var gl = oCanvas.getContext('webgl');
        if (!gl) {
            console.log('不支持webgl');
            // return false;
        }

        // 创建着色器方法，输入参数：渲染上下文，着色器类型，数据源
        function createShader(gl, type, source) {
            var shader = gl.createShader(type); // 创建着色器对象
            gl.shaderSource(shader, source); // 提供数据源
            gl.compileShader(shader); // 编译 -> 生成着色器
            var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
            if (success) {
                return shader;
            }

            console.log(gl.getShaderInfoLog(shader));
            gl.deleteShader(shader);
        }

        var vertexShaderSource = document.getElementById("vertex").text;
        var fragmentShaderSource = document.getElementById("fragment").text;

        var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
        var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
        // 创建程序
        function createProgram(gl, vertexShader, fragmentShader) {
            var program = gl.createProgram();
            gl.attachShader(program, vertexShader);
            gl.attachShader(program, fragmentShader);
            gl.linkProgram(program);
            var success = gl.getProgramParameter(program, gl.LINK_STATUS);
            if (success) {
                return program;
            }
            gl.deleteProgram(program);
        }
        var program = createProgram(gl, vertexShader, fragmentShader);

        var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
        var colorUniformLocation = gl.getUniformLocation(program, "f_color");
        var canvasAttributeLocation = gl.getUniformLocation(program, "u_resolution");
        var positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        // var positions = [
        //     0, 0,
        //     0, 1,
        //     1, 0,
        //     -1, 0,
        //     -1, 1,
        //     0, 0,
        //     0,-0.5,
        //     -0.5, 0,
        // ];
        // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);


        // 渲染
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
        // 清空画布
        gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT);
        // 告诉它用我们之前写好的着色程序（一个着色器对）
        gl.useProgram(program);
        gl.enableVertexAttribArray(positionAttributeLocation);
        // 将绑定点绑定到缓冲数据（positionBuffer）
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

        // 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)
        var size = 2;          // 每次迭代运行提取两个单位数据
        var type = gl.FLOAT;   // 每个单位的数据类型是32位浮点型
        var normalize = false; // 不需要归一化数据
        var stride = 0;        // 0 = 移动单位数量 * 每个单位占用内存（sizeof(type)）
        // 每次迭代运行运动多少内存到下一个数据开始点
        var offset = 0;        // 从缓冲起始位置开始读取
        gl.vertexAttribPointer(
            positionAttributeLocation, size, type, normalize, stride, offset);
        gl.uniform2f(canvasAttributeLocation, gl.canvas.width, gl.canvas.height);

        // 
        // var primitiveType = gl.LINES;
        // var offset = 0;
        // var count = 8;
        // 绘制 （绘制的图形， 缓冲起始位置（从哪个顶点开始绘制）, 绘制需要用到多少个点）
        // gl.drawArrays(primitiveType, offset, count);

        for (var i = 0; i < 50; i++) {
            var x = randomInt(300);
            var y = randomInt(300);
            renderRect(gl, x, y, randomInt(300), randomInt(300));
            gl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1);
            // 绘制矩形
            gl.drawArrays(gl.TRIANGLES, 0, 6);

        }
        // 返回 0 到 range 范围内的随机整数
        function randomInt(range) {
            return Math.random() < 0.5 ? Math.random() * range : -Math.random() * range;
        }
        function renderRect(gl, x, y, width, height) {
            var x1 = x;
            var x2 = x + width;
            var y1 = y;
            var y2 = y + height;

            // 注意: gl.bufferData(gl.ARRAY_BUFFER, ...) 将会影响到
            // 当前绑定点`ARRAY_BUFFER`的绑定缓冲
            // 目前我们只有一个缓冲，如果我们有多个缓冲
            // 我们需要先将所需缓冲绑定到`ARRAY_BUFFER`

            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
                x1, y1,
                x2, y1,
                x1, y2,
                x1, y2,
                x2, y1,
                x2, y2]), gl.STATIC_DRAW);
        }
    </script>
</body>

</html>